
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

/**
 * 手写promise
 */
class MyPromise {
    constructor(fn) {
        // 成功回调
        this.successQueue = [];
        // 失败回调合集
        this.rejectedQueue = [];
        this.status = PENDING;
        this.value  = null;

        const handlesuccessQueue = () => {
            while(this.successQueue.length) {
                let fulfiledFn = this.successQueue.shift();
                fulfiledFn(this.value);
            };
        };
        const handleRejectedQueue = () => {
            while(this.rejectedQueue.length) {
                let rejectedFn = this.rejectedQueue.shift();
                rejectedFn(this.value);
            };
        };

        // 完成状态转变，执行回调队列中的回调函数
        const _resolve = (val) => {
            const fn = () => {
                if(this.status !== PENDING) {
                    return;
                }
                if(val instanceof MyPromise) {
                    val.then((res) => {
                        this.status = FULFILLED;
                        this.value = res;
                        handlesuccessQueue();
                    }, (err) => {
                        this.status = REJECTED;
                        this.value = err;
                        handleRejectedQueue();
                    });
                } else {
                    this.status = FULFILLED;
                    this.value = val;
                    handlesuccessQueue();
                }
            }
            setTimeout(fn, 0);
        }
        // 完成状态Pending到rejected的转变，执行reject队列中的回调函数
        const _reject = (val) => {
            const fn = () => {
                if(this.status !== PENDING) {
                    return;
                }
                this.status = REJECTED;
                this.value = val;
                handleRejectedQueue();
            }
            setTimeout(fn, 0);
        }
        
        try { // 处理外部传入函数执行异常
            fn(_resolve, _reject);            
        } catch(e) {
            
            return _reject(e);
        }
    }

    then(successFn, failFn) {
        return new MyPromise((resolve, reject) => {
            // 执行成功时的回调函数
            const handleSucess = (fn) => {
                console.log('handleSucces',fn);
                try {
                    if(typeof fn === 'function') {
                        const res = fn(this.value);
                        if(res instanceof MyPromise) {
                            console.log('res:',res);
                            res.then(resolve, reject);
                        } else {
                            resolve(res);
                        }
                    } else {
                        resolve(this.value)
                    }
                } catch(e){
                    reject(e);
                }
            }
            // 执行失败时的回调函数
            const handleFail = (fn) => {
                try {
                    if(typeof fn === 'function') {
                        const res = fn(this.value);
                        if(res instanceof MyPromise) {
                            res.then(resolve, reject);
                        } else {
                            resolve(res);
                        }
                    } else {
                        reject(this.value);
                    }
                } catch(e) {
                    reject(e);
                }
            }
            switch(this.status){
                case PENDING:       // 异步任务尚未完成，将回调函数推入相应队列
                    this.successQueue.push(() => {
                        handleSucess(successFn);
                    });
                    this.rejectedQueue.push(() => {
                        handleFail(failFn);
                    });
                    break;
                case FULFILLED:     // 异步任务成功完成，执行成功回调函数
                    handleSucess(successFn);
                    break;
                case REJECTED:      // 异步任务已失败，执行失败回调函数
                    handleFail(failFn);
                    break;
                default:
                    console.log('Promise error status:', this.status);
                    break;
            };
        });
    }

    catch(failFn) {
        return this.then(null, failFn);
    }

    finally(finalFn){
        return this.then(finalFn, finalFn);
    }

    static resolve(val) {
        if(val instanceof MyPromise) {
            return val;
        } else {
            return new MyPromise((resolve, reject) =>{
                resolve(val);
            });
        }
    }

    static reject(val) {
        return new MyPromise((resolve, reject) => {     
            reject(val);
        });
    }
// 必须都跑完
    static all(promiseArray) {
        return new myPromise((resolve, reject) =>{
            const len = promiseArray.length;
            // 计数
            let index = 0;
            let result = [];
            for(let i = 0; i < len; i++) {
                promiseArray[i].then((val) => {
                    index++;
                    result.push(val);
                    // 当所有都执行了，才resolve
                    if(index === len){
                        resolve(result);
                    }
                }, (err) => {
                    reject(err);
                });
            }
       
    });
}

// 看谁先跑完
static race(promiseArray) {
    return new Promise((resolve, reject) =>{
        const len = promiseArray.length;
        for(let i = 0; i < len; i++) {
            promiseArray[i].then((val) => {
                resolve(val);
            }, (err) => {
                reject(err);
            });
        }
    });
}
}  


let pro = new MyPromise((resolve,reject)=>{
    setTimeout(() => {
    resolve(12)
        
    }, 2000);
})

pro.then((e)=>console.log(e));